home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / Expander / Expander Classes / CExpander.cp < prev    next >
Encoding:
Text File  |  1994-11-30  |  8.1 KB  |  346 lines  |  [TEXT/KAHL]

  1. /***********************************************************************************
  2.     CExpander.h
  3.  
  4.     Copyright © 1994 B-Ray Software. All rights reserved.
  5.     Developed using Symantec C++ 7.0.2 and Symantec's TCL library.
  6.     Portions of this code courtesy Symantec, Inc.
  7.  
  8.     This code may be freely distributed as long as this notice remains. This code
  9.     may not be used in any commercial software without the consent of B-Ray Software.
  10.  
  11.     ---
  12.  
  13.     CExpander class provides functionality like the Apple's Finder list windows.
  14.     There is a toggle button associated with each Expander, and clicking on it
  15.     will expose/hide children managed by the Expander. This class does not handle
  16.     selection of children; CExpanderList does.
  17.  
  18. ***********************************************************************************/
  19. #include "CExpander.h"
  20. #include "CExpanderLabel.h"
  21. #include "CExpanderButton.h"
  22. #include "ExpanderMessages.h"
  23.  
  24.  
  25. TCL_DEFINE_CLASS_D1( CExpander, CExpanderPane );
  26.  
  27.  
  28. short const CExpander::kExpanderButtonSize = 16;
  29.  
  30.  
  31. /*
  32.  * CExpander constructor
  33.  *
  34.  * Default constructor - should only be called when created by a file read.
  35.  */
  36.  
  37. CExpander :: CExpander() : CExpanderPane()
  38. {
  39.     itsLabel = NULL;
  40.     itsButton = NULL;
  41.  
  42.     isExpanded = FALSE;
  43.     SetWantsClicks( TRUE );            // we want mouse clicks for our button 
  44.  
  45.     TCL_END_CONSTRUCTOR
  46. }
  47.  
  48.  
  49. /*
  50.  * CExpander constructor
  51.  *
  52.  * Normal constructor - should always be called when creating a new
  53.  * CExpander object.
  54.  */
  55.  
  56. CExpander :: CExpander( CView *anEnclosure, CBureaucrat *aSupervisor, 
  57.                         short aWidth, short aHeight, short aHLoc, short aVLoc,
  58.                         SizingOption aHSizing, SizingOption aVSizing )
  59.                     : CExpanderPane( anEnclosure, aSupervisor, aWidth, aHeight, aHLoc, aVLoc,
  60.                                      aHSizing, aVSizing )
  61. {
  62.     itsLabel = NULL;
  63.     itsButton = NULL;
  64.  
  65.     isExpanded = FALSE;
  66.     SetWantsClicks( TRUE );        // we want mouse clicks for our button
  67.  
  68.     TCL_END_CONSTRUCTOR
  69. }
  70.  
  71.  
  72. /*
  73.  * CExpander destructor
  74.  *
  75.  * Just a place-holder for Inspector
  76.  */
  77.  
  78. CExpander :: ~CExpander()
  79. {
  80.     TCL_START_DESTRUCTOR
  81.  
  82.     /*
  83.      * Since the label and button objects are inherited from CPane, don't blow them away here.
  84.      * Let CPane do it when it gets destroyed - CView disposes of all subviews.
  85.      */
  86.     itsLabel = NULL;
  87.     itsButton = NULL;
  88. }
  89.  
  90.  
  91. void CExpander :: IExpander( void )
  92. {
  93.     MakeExpanderButton();
  94.     MakeExpanderLabel();
  95.     AppendChild( itsLabel );
  96. }
  97.  
  98.  
  99. /*
  100.  * MakeExpanderButton method
  101.  *
  102.  * Protected method to create CExpanderButton object.
  103.  */
  104.  
  105. void CExpander :: MakeExpanderButton( void )
  106. {
  107.     short aWidth = kExpanderButtonSize;
  108.     short aHeight = kExpanderButtonSize;
  109.  
  110.     /*
  111.      * Create button. NOTE: we don't treat the button as a child. Otherwise, our label
  112.      * would be positioned BELOW the button (CColumnizer behavior). We just treat this
  113.      * as a normal pane, and offset the label so they won't overlap.
  114.      */
  115.     itsButton = TCL_NEW( CExpanderButton, ( this, this, aWidth, aHeight ) );
  116. }
  117.  
  118.  
  119. /*
  120.  * MakeExpanderLabel method
  121.  *
  122.  * Protected method to create CExpanderLabel object.
  123.  */
  124.  
  125. void CExpander :: MakeExpanderLabel( void )
  126. {
  127.     short    aWidth = width - ( kExpanderButtonSize + 4 );
  128.     short    aHeight = kExpanderButtonSize + 4;
  129.     short    aHLoc = kExpanderButtonSize + 4;
  130.     short    aVLoc = 0;
  131.  
  132.     itsLabel = TCL_NEW( CExpanderLabel, ( this, this, aWidth, aHeight, aHLoc, aVLoc,
  133.                                           sizFIXEDSTICKY, sizFIXEDSTICKY ) );
  134. }
  135.  
  136.  
  137.  
  138. /*
  139.  * SetMinizedSize method
  140.  *
  141.  * Protected method that sets the size of the pane to just the size of its header, 
  142.  * thus hiding all other children.
  143.  */
  144.  
  145. void CExpander :: SetMinimizedSize( void )
  146. {
  147.     SetExpanderSize( itsLabel->width + kExpanderButtonSize + 4, itsLabel->height );
  148. }
  149.  
  150.  
  151. /*
  152.  * SetExpandedSize method
  153.  *
  154.  * Protected method that sets the size of the pane to the size of all of its 
  155.  * children, making them all viewable.
  156.  */
  157.  
  158. void CExpander :: SetExpandedSize( void )
  159. {
  160.     short    aHeight, aWidth;
  161.  
  162.     GetFamilySize( &aWidth, &aHeight );    // get dimension of rectangle that encloses children
  163.     SetExpanderSize( aWidth, aHeight );    // and set ourselves to that size
  164. }
  165.  
  166.  
  167. /*
  168.  * SetExpandedState method
  169.  *
  170.  * Access method that changes our expansion size.
  171.  */
  172.  
  173. void CExpander :: SetExpandedState( Boolean fExpanded )
  174. {
  175.     if ( fExpanded != isExpanded ) {    // ignore repeat calls
  176.         isExpanded = fExpanded;            // record new value
  177.         if ( isExpanded )
  178.             SetExpandedSize();            // become bigger
  179.         else
  180.             SetMinimizedSize();            // become smaller
  181.  
  182.         ValidateHeader();                // remove header from update activity
  183.  
  184.         itsButton->SetValue( isExpanded );    // update our button to reflect change
  185.     }
  186. }
  187.  
  188.  
  189. /*
  190.  * ValidateHeader method
  191.  *
  192.  * Removes label and button panes from update activity caused by our changing sizes.
  193.  * Helps reduce flicker caused by excessive redraws.
  194.  */
  195.  
  196. void CExpander :: ValidateHeader( void )
  197. {
  198.     LongRect    anAperture;
  199.     Rect        validRect;
  200.  
  201.     itsButton->Prepare();
  202.     itsButton->GetAperture( &anAperture );                // get header's frame
  203.     itsButton->FrameToQDR( &anAperture, &validRect );    // put into QD coords
  204.     ValidRect( &validRect );                            // remove from update region
  205.  
  206.     itsLabel->Prepare();
  207.     itsLabel->GetAperture( &anAperture );                // get header's frame
  208.     itsLabel->FrameToQDR( &anAperture, &validRect );    // put into QD coords
  209.     ValidRect( &validRect );                            // remove from update region
  210. }
  211.  
  212.  
  213. /*
  214.  * ChangeSelf method - OVERRIDE
  215.  *
  216.  * Adjust ourself to reflect the changes of our children.
  217.  */
  218.  
  219. void CExpander :: ChangeSelf( long changedIndex, Rect *delta )
  220. {
  221.     short    aWidth, aHeight;
  222.  
  223.     if ( isExpanded ) {
  224.         SetExpandedSize();
  225.     }
  226.     else {
  227.         SetMinimizedSize();
  228.     }
  229.  
  230.     /*
  231.      * If there is no stuff to show when expanded, disable our button.
  232.      */
  233.     GetFamilySize( &aWidth, &aHeight );    // get dimension of rectangle that encloses children
  234.     if ( GetNumberChildren() == 1 || aHeight == itsLabel->height ) {
  235.         itsButton->SetEnabled( FALSE );
  236.         if ( isExpanded ) {
  237.             itsButton->SetValue( FALSE );
  238.         }
  239.     }
  240.     else {
  241.         itsButton->SetEnabled( TRUE );
  242.     }
  243. }
  244.  
  245.  
  246. /*
  247.  * DoCommand method - OVERRIDE
  248.  *
  249.  * Handles cmdExpandPane and cmdUnexpandPane messages that are sent from our button.
  250.  * Others could send them too, but don't know why...
  251.  */
  252.  
  253. void CExpander :: DoCommand( long theCommand )
  254. {
  255.     if ( theCommand == cmdExpandPane )
  256.         SetExpandedState( TRUE );
  257.     else if ( theCommand == cmdUnexpandPane )
  258.         SetExpandedState( FALSE );
  259.     else
  260.         CExpanderPane::DoCommand( theCommand );
  261. }
  262.  
  263.  
  264. /*
  265.  * DoKeyDown method - OVERRIDE
  266.  *
  267.  * Handles key down events. We only look for RETURN keystrokes
  268.  */
  269.  
  270. void CExpander :: DoKeyDown( char theChar, Byte keyCode, EventRecord *macEvent )
  271. {
  272.     if ( theChar == kEnterKey || theChar == '\r' && itsButton->GetEnabled() ) {
  273.         SetExpandedState( ! isExpanded );
  274.     }
  275.     else {
  276.         CExpanderPane::DoKeyDown( theChar, keyCode, macEvent );
  277.     }
  278. }
  279.  
  280.  
  281. /*
  282.  * ParentMessage method - OVERRIDE
  283.  *
  284.  * Handles the kExpanderPrinting message from the parent. When our parent
  285.  * pane is told to start printing, we want to be expanded so that all of our
  286.  * children will be drawn. We remember the previous state of our expansion,
  287.  * expand ourselves, and then wait for another kExpanderPrinting message to
  288.  * set ourselves back to the saved state. The param value is treated as a
  289.  * boolean value telling us if we are beginning or ending the printing phase.
  290.  */
  291.  
  292. void CExpander :: ParentMessage( long message, void *param )
  293. {
  294.     if ( message == kExpanderPrinting ) {        // family tree is being printed
  295.         if ( param ) {                            // before printing
  296.             savedExpanderFlag = isExpanded;        // save present state
  297.             SetExpandedState( TRUE );            // make sure we are expanded
  298.         }
  299.         else {                                    // after printing
  300.             SetExpandedState( savedExpanderFlag );    // reset to previous state
  301.         }
  302.         TellChildren( message, param );            // tell our children the same message
  303.     }
  304.     else {
  305.         CExpanderPane::ParentMessage( message, param );
  306.     }
  307. }
  308.  
  309.  
  310. /*
  311.  * PutTo method - OVERRIDE
  312.  *
  313.  * Writes to the stream all of the info we need to save.
  314.  */
  315.  
  316. void CExpander :: PutTo( CStream &stream )
  317. {
  318.     stream << isExpanded;
  319.  
  320.     CExpanderPane::PutTo( stream );
  321.  
  322.     stream << itsLabel;
  323.     stream << itsButton;
  324. }
  325.  
  326.  
  327. /*
  328.  * GetFrom method - OVERRIDE
  329.  *
  330.  * Reads from the stream all of the info that we saved.
  331.  */
  332.  
  333. void CExpander :: GetFrom( CStream &stream )
  334. {
  335.     Boolean    aFlag;
  336.  
  337.     stream >> aFlag;
  338.  
  339.     CExpanderPane::GetFrom( stream );
  340.  
  341.     itsLabel = (CExpanderLabel *)stream.GetView( this, this );
  342.     itsButton = (CExpanderButton *)stream.GetView( this, this );
  343.  
  344.     SetExpandedState( aFlag );
  345. }
  346.